import {observable, action} from 'mobx'
import {message} from "antd";
import {Cluster, HostPathVolume, LivenessProbe, CreateAppParam, NT, ResourceModel} from './interfaces'
import apis from "../../config/apis";
import request from '../../utils/request'
import {IOneSelectData} from '../../components/OneSelect'
import {CascaderOptionType} from "antd/lib/cascader";
import {MirrorData} from './interfaces'


class Store {
    init = () => {
        this.createStatus = '完成'
        this.current = 0
        //应用配置必须的参数
        this.namespace = undefined
        this.namespace_cn = undefined
        this.app_name = undefined
        this.app_id = undefined
        this.node_affinity_labels = []
        this.describe = undefined
        //容器配置必须的参数
        this.addr = undefined
        this.clusters_cn = new Array<{
            cluster_name: string
            replicas: number
            edit: boolean
        }>()
        this.clusters = new Array<Cluster>()
        this.cpu = 0
        this.mem = 0
        this.gpu_num = 0
        this.gpu_id = 0
        this.lbArr = new Array<{
            container_port: number | undefined
            protocol: 'TCP' | 'UDP' | undefined
            edit: boolean
        }>()
        this.envArr = new Array<{
            key: string
            value: string
            edit: boolean
        }>()
        this.mirror_id = 0
        this.mirror_type = 2
        this.mirror_tag_id = 0
        this.image = ''
        this.is_check_resource_quotas = true
        this.host_path_volumes = new Array<HostPathVolume>()
        this.env = undefined
        this.is_liveness_probe = false
        this.liveness_probe = undefined
        this.restart_policy = 'Always'
        this.labels = undefined
        this.command = undefined
        this.namespaces = new Array<IOneSelectData>()
        this.areas = new Array<IOneSelectData>()
        this.clusterArr = new Array<IOneSelectData>()
        this.areaMap = {}
        this.nodeTypes = new Array<NT>()
        this.nodeType = {} as NT
        this.resourceQuotaIndex = 0
        this.resourceQuota = {} as ResourceModel
        this.loading = false
        this.getNamespaces()
        this.getArea()
    }
    @observable createStatus = '完成'
    @observable current = 0
    //应用配置必须的参数
    @observable namespace: string | undefined = undefined
    @observable namespace_cn: string | undefined = undefined
    @observable app_name: string | undefined = undefined
    @observable app_id: string | undefined = undefined
    @observable node_affinity_labels: string[] = []
    @observable describe: string | undefined = undefined
    //容器配置必须的参数
    @observable addr: string | undefined = undefined
    @observable clusters_cn = new Array<{
        cluster_name: string | undefined
        replicas: number
        edit: boolean
    }>()
    @observable clusters = new Array<Cluster>()
    @observable cpu = 0
    @observable mem = 0
    @observable gpu_num = 0
    @observable gpu_id = 0
    @observable lbArr = new Array<{
        container_port: number | undefined
        protocol: 'TCP' | 'UDP' | undefined
        edit: boolean
    }>()
    @observable envArr = new Array<{
        key: string
        value: string
        edit: boolean
    }>()
    @observable mirror_id = 0
    @observable mirror_type = 2
    @observable mirror_tag_id = 0
    @observable image: string | undefined = ''
    @observable is_check_resource_quotas = true
    @observable host_path_volumes = new Array<HostPathVolume>()
    @observable env: { [prop: string]: string } | undefined = undefined
    @observable is_liveness_probe = false
    @observable liveness_probe: LivenessProbe | undefined = undefined
    @observable restart_policy: 'Always' | 'OnFailure' | 'Never' = 'Always'
    @observable labels: { [prop: string]: string } | undefined = undefined
    @observable command: string[] | undefined = undefined
    //检查参数是否在编辑
    checkEdit = (): boolean => {
        //clusters_cn
        for (let item of this.clusters_cn) {
            if (item.edit) {
                message.warning('集群选择还未确定')
                return false
            }
        }
        //lbArr
        for (let item of this.lbArr) {
            if (item.edit) {
                message.warning('负载均衡编辑还未确定')
                return false
            }
        }
        //envArr
        for (let item of this.envArr) {
            if (item.edit) {
                message.warning('环境变量编辑还未确定')
                return false
            }
        }
        //host_path_volumes
        for (let item of this.host_path_volumes) {
            if (item.edit) {
                message.warning('目录映射编辑还未确定')
                return false
            }
        }
        return true
    }

    //初始化数据
    //业务系统
    @observable namespaces = new Array<IOneSelectData>()
    @action getNamespaces = async () => {
        const api = apis.GetNamespace
        const resp = await request(api)
        if (!resp) return
        const {list} = resp
        const arr = new Array<IOneSelectData>()
        for (let i = 0; i < list.length; i++) {
            const itm = list[i]
            arr.push({
                label: itm.name_cn,
                value: itm.name_en
            })
        }
        this.namespaces = arr
    }
    //区域
    @observable areas = new Array<IOneSelectData>()
    @observable clusterArr = new Array<IOneSelectData>()
    areaMap: {
        [prop: string]: {
            [prop: string]: string
        }
    } = {}

    @action getArea = async () => {
        const resp = await request(apis.GetAreaCluster)
        if (!resp) return
        const {areas} = resp
        const arr = new Array<IOneSelectData>()
        for (let i = 0; i < areas.length; i++) {
            const item = areas[i]
            let area: IOneSelectData = {} as IOneSelectData
            let clus = new Array<IOneSelectData>()
            if (!this.areaMap[item.area_name]) this.areaMap[item.area_name] = {}
            if (item && item.cluster && item.cluster.length > 0) {
                for (let j = 0; j < item.cluster.length; j++) {
                    const clu = item.cluster[j]
                    clus.push({label: clu.cluster_name, value: clu.cluster_label})
                    if (!this.areaMap[item.area_name][clu.cluster_label]) this.areaMap[item.area_name][clu.cluster_label] = clu.cluster_name
                }
            }
            area.label = item.area_name
            area.value = item.area_name
            area.children = clus
            arr.push(area)
        }
        this.areas = arr
    }
    @observable nodeTypes = new Array<NT>()
    @observable nodeType: NT = {} as NT
    @observable resourceQuotaIndex = 0
    @observable resourceQuota: ResourceModel = {} as ResourceModel
    @action getNodeTypes = async () => {
        let cls: string[] = []
        for (let i = 0; i < this.clusters.length; i++) {
            if (this.clusters[i].cluster_label) cls.push(<string>this.clusters[i].cluster_label)
        }
        const resp = await request(apis.GetNodeType, {cluster_labels: cls})
        if (!resp) {
            this.nodeTypes = new Array<NT>()
        }
        this.nodeTypes = resp as Array<NT>
    }

    // 获取健康检测
    @action setLivenessProbe = (obj: { [prop: string]: any }) => {
        let liveness_probe = this.liveness_probe
        if (!liveness_probe) liveness_probe = {
            type: 0,
            command: undefined,
            port: undefined,
            path: undefined,
            headers: undefined,
            initial_delay_seconds: undefined,
            period_seconds: undefined,
            timeout_seconds: undefined,
            edit: undefined
        };
        this.liveness_probe = Object.assign(liveness_probe, obj)
    }

    checkParams = () => {
        let tip = ''
        if (!this.clusters || !this.clusters.length) tip = '请选择集群'
        for (let c of this.clusters) {
            if (!c.cluster_label) {
                tip = '集群配置错误，请重新配置'
                break
            }
            if (!c.replicas || c.replicas <= 0) {
                tip = '集群配置实例数不可小于等于0'
                break
            }
        }
        if (!this.namespace) tip = '请选择业务系统'
        if (!this.app_name) tip = '请输入应用名称'
        if (!this.app_id) tip = '请正确输入APPID'
        if (!/^[qwertyuiopasdfghjklzxcvbnm][qwertyuiopasdfghjklzxcvbnm1234567890-]+$/.test(this.app_id as string)) tip = '请正确输入APPID，字母开头，包含数字，字母，中横线-。'
        if (!this.mirror_id || !this.mirror_tag_id) tip = '请选择镜像'
        if (!this.resourceQuota) tip = '请选择容器规格'
        if (tip) {
            message.warning(tip)
            return false
        }
        return true
    }

    @action submit = async () => {
        if (!this.checkParams() && !this.checkEdit()) return
        const api = apis.CreateApp
        const params: CreateAppParam = {
            addr: this.addr,
            clusters: this.clusters && this.clusters.length ? [...this.clusters] : new Array<Cluster>(),
            namespace: this.namespace,
            app_name: this.app_name,
            app_id: this.app_id,
            describe: this.describe,
            mirror_id: this.mirror_id,
            mirror_tag_id: this.mirror_tag_id,
            mirror_type: this.mirror_type,
            node_affinity_labels: this.resourceQuota ? {type: [this.nodeType.node_type]} : undefined,
            cpu: this.resourceQuota.cpu,
            mem: this.resourceQuota.mem,
            gpu_num: this.resourceQuota.gpu_num,
            gpu_id: this.resourceQuota.gpu_id,
            is_proxy: this.lbArr && this.lbArr.length > 0,
            container_port: this.lbArr && this.lbArr.length > 0 ? this.lbArr[0].container_port : undefined,
            protocol: this.lbArr && this.lbArr.length > 0 ? this.lbArr[0].protocol : undefined,
            is_check_resource_quotas: true,
            host_path_volumes: this.host_path_volumes ? [...this.host_path_volumes] : undefined,
            env: (() => {
                if (this.envArr && this.envArr.length) {
                    let data: { [prop: string]: string } = {}
                    this.envArr.forEach(v => {
                        data[v.key] = v.value
                    })
                    return data
                }
                return undefined
            })(),
            is_liveness_probe: (this.liveness_probe && this.liveness_probe.type > 0) ? true : false,
            liveness_probe: this.liveness_probe ? this.liveness_probe : undefined,
            restart_policy: this.restart_policy,
            labels: undefined,
            command: this.command && this.command.length ? [...this.command] : undefined
        }
        const resp = await request(api, params)
        if (!resp) return false
        return true
    }

    //加载中
    @observable loading = false
    @action setLoading = (): void => {
        this.loading = true
        setTimeout(() => {   //加载中
            this.loading = false
        }, 2000)
    }
    @observable pubMirrors: Array<CascaderOptionType> = []
    @observable priMirrors: Array<CascaderOptionType> = []
    @action GetMirrorSelectData = async () => {
        const api = apis.GetMirrorSelectData
        const resp = await request(api, {id: this.namespace})
        if (!resp) return
        console.log(resp)
        let data = resp as MirrorData
        if (data.pub_mirror && data.pub_mirror.length) {
            let poArr = new Array<CascaderOptionType>()
            for (let o of data.pub_mirror) {
                let po: CascaderOptionType = {}
                po.label = o.mirror_address
                po.value = o.id
                if (o.MirrorTags && o.MirrorTags.length) {
                    let toArr = new Array<CascaderOptionType>()
                    for (let t of o.MirrorTags) {
                        let to: CascaderOptionType = {}
                        to.label = t.tag_name
                        to.value = t.id
                        toArr.push(to)
                    }
                    po.children = toArr
                }
                poArr.push(po)
            }
            this.pubMirrors = poArr
        }
        if (data.pri_mirror && data.pri_mirror.length) {
            let poArr = new Array<CascaderOptionType>()
            for (let o of data.pri_mirror) {
                let po: CascaderOptionType = {}
                po.label = o.mirror_address
                po.value = o.id
                if (o.MirrorTags && o.MirrorTags.length) {
                    let toArr = new Array<CascaderOptionType>()
                    for (let t of o.MirrorTags) {
                        let to: CascaderOptionType = {}
                        to.label = t.tag_name
                        to.value = t.id
                        toArr.push(to)
                    }
                    po.children = toArr
                }
                poArr.push(po)
            }
            this.priMirrors = poArr
        }
    }
}

export default new Store()